博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
8.6 如何限制未认证用户访问有权限网页
阅读量:4095 次
发布时间:2019-05-25

本文共 3572 字,大约阅读时间需要 11 分钟。

——————————前言——————————————

上节我们讲了注册时向用户发送确认邮件, 确认成功把用户的confirm属性值改为1, 默认为0.

本节我们来利用这个confirm值来做些文章, 让未确认的用户登录以后不能看到主页, 显示一个页面提醒用户未确认账户, 让用户登录邮箱确认账户, 或者是选择重新发送确认邮件。

——————————————————————————

一. 修改|-app/-auth/views.py

@auth.before_app_requestdef before_request():    if current_user.is_authenticated() \  #用户已登录且        and not current_user.confirm \  #用户未认证且        and request.endpoint[:5] != 'auth.' \  #请求端点不为auth蓝本定义的路由        and request.endpoint != 'static':  #请求断点不为static        return redirect(url_for('auth.unconfirmed'))  #重定向@auth.route('/unconfirmed')def unconfirmed():    if current_user.is_anonymous or current_user.confirm:  #防止已用户重复访问该链接        return redirect(url_for('main.index'))    return render_template('auth/unconfirmed.html')  #返回未确认页面, 页面内容见标题二@auth.route('/confirm')@login_requireddef resend_confirmation():  #重新发送确认邮件    token = current_user.generate_token()    send_mail(current_user.email, 'Confirm your account', 'auth/email/confirm', user=current_user, token=token)    flash('a confirm email has been sent to your email.')    return redirect(url_for('main.index'))

代码说明:

    第二章我们讲过请求钩子, before_request注册一个函数, 在所有请求之前运行, auth蓝本注册的请求钩子的作用域只在该蓝本定义的路由中有效, 如果想把作用域应用的程序全局, 就要使用before_app_request。

    这样before_request函数就会在所有请求之前运行, 该函数的作用是使未认证用户登录以后重定向到未认证提醒页面,所以要加上current_user.is_authenticated() 和not current_user.confirm这两个判断条件,。

    然后程序就会重定向到auth.unconfirmed, 可是浏览器在发送auth.unconfirmed请求以后, 还是会先运行before_request函数, 就会再次重定向, 陷入循环, 因此我们加上request.endpoint[:5] != 'auth.'(endpoint存储的是请求端点, 如主页的请求断点就是main.index,)这个条件,这样访问auth蓝本的路由就不会重定向了。

    auth.unconfirmed路由返回提醒页面, 提醒页面包括一链接, 指向auth.resend_confirmation, 重新发送认证邮件。

    点击链接后, 程序重新发送验证邮件, 用户登录邮箱进行确认即可。

二. 修改|-app/templates/auth/unconfirmed.html

{% extends 'base.html' %}{% block title %}Flasky - Confirm your account{% endblock %}{% block page_content %}

三. 效果演示与代码说明

本次用登录sherry用户的过程来讲解程序的执行过程:

可见sherry用户未进行验证, 我们用浏览器访问程序主页,before_app_request注册的函数会在每个请求之前运行, 但是里面的限制条件只有已登录的未验证用户才会重定向, 所以未登录之前我们不用考虑这个钩子, 程序直接显示主页, 点击右上角登录链接显示登录页面:

输入信息并点击提交按钮以后, 我们就要考虑钩子的作用了, 见处理登陆的视图函数:

@auth.route('/login', methods=['GET', 'POST'])def login():    form = LoginForm()    if form.validate_on_submit():        user = User.query.filter_by(email=form.email.data).first()        if user and user.verify_password(form.password.data):            login_user(user, form.remember_me)            return redirect(request.args.get('next') or url_for('main.index'))        flash('Invalid username or password.')    return render_template('auth/login.html', form=form)

  我们点击提交按钮以后执行if语句块, 经过密码验证以后代码会登录用户, 并且返回主页的重定向, 浏览器发出请求主页的url后, 先执行钩子函数, 此时用户已登录, 并且未验证, 访问的又不是端点又不是auth., 于是重定向到auth.unconfirmed; 

  浏览器再发出请求auth.unconfirmed的url, 因为钩子函数中的条件request.endpoint[:5] != 'auth.', 所以所有对auth蓝本定义的路由的请求都可以忽略钩子函数, 返回auth/unconfirmed.html提醒页面:

点击链接, 访问auth.resend_confirmation视图函数, 重新发送邮件;

发完之后提示flash消息, 并且重定向到主页, 因为钩子函数的原因, 重定向到auth.unconfirmed:

我们登录邮箱, 发现一封新邮件:

打开后:

发现验证链接, 点击链接, 访问auth.confirm视图函数, 进行用户的认证, 认证通过, 用户的confirm属性值变为1:

重定向到主页, 因为此时用户已经认证, 所以可以忽略钩子函数, 程序返回主页:

*演示过程的说明都是按照代码的执行顺序讲解的。

四. request.endpoint != 'static'

注释:钩子函数中的request.endpoint != 'static'表明, 请求的端点是static, 可以忽略钩子函数:

可能有人会问, 我们的路由都是由auth和main蓝本定义的, 哪有名为static的端点?

还记得第二章的url_map吗:

最后一个端点就是static, 举例来说, 我们访问127.0.0.1:5000/static/favicon.ico就会得到我们的静态文件favicon.ico。

你可能感兴趣的文章
React非嵌套组件通信
查看>>
浏览器兼容性问题解决方案 · 总结
查看>>
一个很棒的Flutter学习资源列表
查看>>
为什么你应该放弃React老的Context API用新的Context API
查看>>
Koa2初体验
查看>>
Koa 2 初体验(二)
查看>>
Koa2框架原理解析和实现
查看>>
C++模板
查看>>
【C#】如何实现一个迭代器
查看>>
【C#】利用Conditional属性完成编译忽略
查看>>
【Unity】微信登录后将头像存为bytes,将bytes读取成sprite图片
查看>>
【Unity】使用GPS定位经纬度
查看>>
最小费用流 Bellman-Ford与Dijkstra 模板
查看>>
mapReduce(3)---入门示例WordCount
查看>>
hbase(3)---shell操作
查看>>
hbase(1)---概述
查看>>
hbase(5)---API示例
查看>>
SSM-CRUD(1)---环境搭建
查看>>
Nginx(2)---安装与启动
查看>>
springBoot(5)---整合servlet、Filter、Listener
查看>>